Truck Loading
The first problem is to find the optimal packaging of products in vehicles (trucks in this example) so that
-
Minimum number of trucks are used
-
Maximum volume is ocupied by the products collectively in all the trucks
This is with the reasonable assumption that trucks with more capacity will cost more, so in case two trucks can fully accomodate a set of items, the smaller one will be preferred.
Tech Stack
Library used for optimal bin-packing is py3dbp
More specifically, a modified version of py3dbp
which allows color coded images of trucks with deliveries was used.
Code snippet
from py3dbp import Packer, Bin, Item, Painter
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def get_optimum(stats):
unfitted = min(stats, key=lambda x: x[2])[2]
stats = [stat for stat in stats if stat[2] == unfitted]
optimum = max(stats, key=lambda x: x[1])
return optimum
def process_items(deliveries, trucks):
delivery_color, color_list, color_index = [], ["yellow", "green", "blue", "pink", "red"], 0
packer = Packer()
for t in trucks:
packer.addBin(Bin(t["name"], (t["length"], t["width"], t["height"]), t["weight"], 0, 0))
for item in deliveries:
for i in range(item.num_cases):
packer.addItem(
Item(
partno=i,
name=item.delivery_number,
typeof="cube",
WHD=(item.length, item.width, item.height),
weight=1,
level=1,
loadbear=100,
updown=True,
color=color_list[color_index],
)
)
delivery_color.append([item.delivery_number, color_list[color_index]])
if color_index == len(color_list) - 1:
color_index = 0
else:
color_index += 1
packer.pack(
bigger_first=True,
distribute_items=False,
fix_point=True,
check_stable=True,
support_surface_ratio=0.75,
number_of_decimals=0,
)
packer.putOrder()
stats = []
for i in range(len(packer.bins)):
b = packer.bins[i]
vol_used = 0
for item in b.items:
vol_used += float(item.getVolume())
stats.append([i, round((vol_used / float(b.getVolume())) * 100, 2), len(b.unfitted_items)])
optimum = get_optimum(stats)
bin = packer.bins[optimum[0]]
painter = Painter(bin)
fig = painter.plotBoxAndItems(title=bin.partno, alpha=0.8, write_num=False, fontsize=20)
grid_size = 8
x, y, z = np.indices((grid_size, grid_size, grid_size))
cube = (x >= 2) & (x < 6) & (y >= 2) & (y < 6) & (z >= 2) & (z < 6)
voxelarray = cube
colors = np.empty(voxelarray.shape, dtype=object)
colors[cube] = "blue"
plt.savefig("public/truck.png")
plt.close("all")
return optimum[1], optimum[2], delivery_color